<template>
  <div :ref="refKeys.innerTable" class="table-layout-wrap">
    <div :ref="refKeys.innerTableWrap" class="box-wrapper" style="height:100%">
      <div class="search-bar run-search-bar" style="background:none;">
        <div>
          <slot name="search-bar"></slot>
        </div>
        <div>
          <slot name="handle-bar"></slot>
        </div>
      </div>
      <slot />
      <div class="table-area">
        <!-- :max-height="tableMaxHeight" -->
        <Table
          :ref="refKeys.table"
          :data="insideTableData"
          :columns="insideColumns"
          :stripe="stripe"
          :border="border"
          :show-header="showHeader"
          :width="width"
          :height="tableHeight"
          :loading="loading"
          :disabled-hover="disabledHover"
          :highlight-row="highlightRow"
          :row-class-name="rowClassName"
          :size="size"
          :no-data-text="noDataText"
          :no-filtered-data-text="noFilteredDataText"
          @on-current-change="onCurrentChange"
          @on-select="onSelect"
          @on-select-cancel="onSelectCancel"
          @on-select-all="onSelectAll"
          @on-selection-change="onSelectionChange"
          @on-sort-change="onSortChange"
          @on-filter-change="onFilterChange"
          @on-row-click="onRowClick"
          @on-row-dblclick="onRowDblclick"
          @on-expand="onExpand"
        >
          <!-- <slot slot-scope="{ row, index }" slot="radio" v-if="showCheckbox">
            <template>
              <Checkbox :value="checked" @click.native.stop="handleClick" @on-change="toggleSelect" :disabled="disabled"></Checkbox>
            </template>
          </slot>-->
          <slot name="header" slot="header"></slot>
          <slot name="footer" slot="footer"></slot>
          <slot name="loading" slot="loading"></slot>
          <slot name="action" slot="action"></slot>
          <slot name="radio" slot="radio"></slot>
        </Table>
        <page
          v-if="showPage"
          ref="pages"
          :total="total"
          :current="pageNum"
          :pageSize="pageSize"
          :pageSizeOpts="pageSizeOpts"
          @on-page-size-change="onSize"
          @on-change="changePage"
        />
      </div>
    </div>
  </div>
</template>

<script>
import TablesEdit from './edit.vue'
import handleBtns from './handle-btns'
import Page from '_c/page'
// import RadioCell from './radio-cell';
import './index.less'
export default {
  name: 'Tables',
  components: {
    Page
  },
  props: {
    value: {
      type: Array,
      default() {
        return []
      }
    },

    // 行设置
    columns: {
      type: Array,
      default() {
        return []
      }
    },
    showCheckbox: {
      type: Boolean,
      default() {
        return true
      }
    },
    size: {
      type: String,
      default() {
        return 'small'
      }
    },
    width: {
      type: [Number, String]
    },
    height: {
      type: [Number, String]
    },
    stripe: {
      type: Boolean,
      default: true
    },
    border: {
      type: Boolean,
      default: true
    },
    showHeader: {
      type: Boolean,
      default: true
    },
    highlightRow: {
      type: Boolean,
      default: false
    },
    rowClassName: {
      type: Function,
      default() {
        return ''
      }
    },
    context: {
      type: Object
    },
    noDataText: {
      type: String
    },
    noFilteredDataText: {
      type: String
    },
    disabledHover: {
      type: Boolean
    },
    loading: {
      type: Boolean,
      default: false
    },
    /**
     * @description 全局设置是否可编辑
     */
    editable: {
      type: Boolean,
      default: false
    },
    /**
     * @description 是否可搜索
     */
    searchable: {
      type: Boolean,
      default: false
    },
    /**
     * @description 搜索控件所在位置，'top' / 'bottom'
     */
    searchPlace: {
      type: String,
      default: 'top'
    },
    // 分页配置开始
    showPage: {
      // 显示分页
      type: Boolean,
      default() {
        return true
      }
    },
    // 当前页
    pageNum: {
      type: Number,
      default() {
        return 1
      }
    },
    // 总条数
    total: {
      type: Number | String,
      default() {
        return '0'
      }
    },
    // 每页显示条数
    pageSize: {
      type: Number,
      default() {
        return 10
      }
    },
    pageSizeOpts: {
      type: Array,
      default() {
        return [10, 20, 30, 40]
      }
    },
    fit: {
      type: Boolean,
      default() {
        return false
      }
    }
    // 分页配置介绍
  },
  /**
   * Events
   * @on-start-edit 返回值 {Object} ：同iview中render函数中的params对象 { row, index, column }
   * @on-cancel-edit 返回值 {Object} 同上
   * @on-save-edit 返回值 {Object} ：除上面三个参数外，还有一个value: 修改后的数据
   */
  data() {
    return {
      insideColumns: [],
      insideTableData: [],
      edittingCellId: '',
      edittingText: '',
      searchValue: '',
      searchKey: '',
      currentRow: undefined,
      tableHeight: undefined, // 表格高度
      autoMaxHeight: true,
      refKeys: {
        innerTable: Symbol('innerTable'),
        innerTableWrap: Symbol('innerTableWrap'),
        table: Symbol('table')
      },
      param: {
        page: this.pageSize,
        size: this.pageSize
      },
      changePageFlag: false
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.tableHeight = this.height || 'auto'
      if (!this.autoMaxHeight) return
      if (this.fit) {
        this.setTableScroll()
        // 窗口变化重新计算
        window.addEventListener('resize', this.setTableScroll)
      }
    })
    this.handleColumns(this.columns)
    this.setDefaultSearchKey()
    this.handleTableData()
  },
  destroyed() {
    if (this.fit) {
      window.removeEventListener('resize', this.setTableScroll)
    }
  },
  methods: {
    // 设置表格内滚动
    setTableScroll() {
      const { table, innerTable, innerTableWrap } = this.refKeys
      // 获取表格元素
      const tbody = this.$refs[table].$el
      // 父级元素
      const parentNode = this.$refs[innerTable].parentElement
      // 若父元素没有设置高度 则自动设置
      if ((!parentNode.style.height && !parentNode.style.minHeight) || this.fit) {
        parentNode.style.height = '100%'
        parentNode.style.width = '100%'
      }

      // 获取整体高度
      let boxHeight = this.$refs[innerTable].clientHeight
      // eslint-disable-next-line no-unused-vars
      let boxWidth = this.$refs[innerTable].clientWidth
      // 获取内框高度
      const _innerTableWrap = this.$refs[innerTableWrap].clientHeight
      const _innerTableWrapW = this.$refs[innerTableWrap].clientWidth
      // 获取表格以外元素高度
      const rests = _innerTableWrap - tbody.clientHeight
      // eslint-disable-next-line no-unused-vars
      const restsW = _innerTableWrapW - tbody.clientWidth

      // 设置最大表格高度
      const parentHeight = parentNode.clientHeight
      // eslint-disable-next-line no-unused-vars
      const parentWidth = parentNode.clientWidth
      // if (this.fit) {
      //   this.width = parentWidth - restsW - 10;
      //   // this.width = '100%';
      //   // console.log(this.width);
      //   // this.$emit('on-changeWidth', this.width);
      // }
      if (this.fit && parentHeight > rests) {
        this.tableHeight = parentHeight - rests + 1
      } else {
        // this.height = 'auto';
        this.tableHeight = boxHeight - rests + 1
      }
    },
    initCheckbox() {
      // do nothing
    },
    suportEdit(item, index) {
      item.render = (h, params) => {
        return h(TablesEdit, {
          props: {
            params: params,
            value: this.insideTableData[params.index][params.column.key],
            edittingCellId: this.edittingCellId,
            editable: this.editable
          },
          on: {
            input: val => {
              this.edittingText = val
            },
            'on-start-edit': params => {
              this.edittingCellId = `editting-${params.index}-${params.column.key}`
              this.$emit('on-start-edit', params)
            },
            'on-cancel-edit': params => {
              this.edittingCellId = ''
              this.$emit('on-cancel-edit', params)
            },
            'on-save-edit': params => {
              this.value[params.row.initRowIndex][params.column.key] = this.edittingText
              this.$emit('input', this.value)
              this.$emit('on-save-edit', Object.assign(params, { value: this.edittingText }))
              this.edittingCellId = ''
            }
          }
        })
      }
      return item
    },
    surportHandle(item) {
      let options = item.options || []
      let insideBtns = []
      options.forEach(item => {
        if (handleBtns[item]) insideBtns.push(handleBtns[item])
      })
      let btns = item.button ? [].concat(insideBtns, item.button) : insideBtns
      item.render = (h, params) => {
        params.tableData = this.value
        return h(
          'div',
          btns.map(item => item(h, params, this))
        )
      }
      return item
    },
    handleColumns(columns) {
      this.insideColumns = columns.map((item, index) => {
        let res = item
        if (res.editable) res = this.suportEdit(res, index)
        if (res.key === 'handle') res = this.surportHandle(res)
        return res
      })
    },
    setDefaultSearchKey() {
      this.searchKey =
        this.columns[0].key !== 'handle' ? this.columns[0].key : this.columns.length > 1 ? this.columns[1].key : ''
    },

    handleClear(e) {
      if (e.target.value === '') this.insideTableData = this.value
    },
    handleSearch() {
      this.insideTableData = this.value.filter(item => item[this.searchKey].indexOf(this.searchValue) > -1)
    },
    handleTableData() {
      this.insideTableData = this.value.map((item, index) => {
        let res = item
        res.initRowIndex = index
        return res
      })
    },
    exportCsv(params) {
      this.$refs.refKeys.table.exportCsv(params)
    },
    clearCurrentRow() {
      this.$refs.talbesMain.clearCurrentRow()
    },
    getHighlightRow() {
      return this.currentRow
    },
    onCurrentChange(currentRow, oldCurrentRow) {
      this.currentRow = Object.assign({}, currentRow)
      this.$emit('on-current-change', currentRow, oldCurrentRow)
    },
    onSelect(selection, row) {
      // if (!this.multiple) {
      //   let data = {};

      //   for (let i in this.objData) {
      //     if (parseInt(i) === _index) {
      //       data = this.objData[i];
      //       break;
      //     }
      //   }
      //   const status = !data._isChecked;

      //   this.objData[_index]._isChecked = status;

      //   const selection = this.getSelection();
      //   this.$emit(status ? 'on-select' : 'on-select-cancel', selection, JSON.parse(JSON.stringify(this.data[_index])));
      //   this.$emit('on-selection-change', selection);
      // }
      this.$emit('on-select', selection, row)
    },
    onSelectCancel(selection, row) {
      // this.insideTableData = this.insideTableData.map((newRow, index) => {
      //   newRow._isHover = false;
      //   if (newRow._highlight && !newRow._disabled) {
      //     newRow._isHighlight = false;
      //   }
      //   return newValue;
      // });
      this.$emit('on-select-cancel', selection, row)
    },
    onSelectAll(selection) {
      // let data = {};
      // this.insideTableData = this.insideTableData.map((newRow, index) => {
      //   newRow._isHover = false;
      //   if (newRow._highlight && !newRow._disabled) {
      //     newRow._isHighlight = true;
      //   }
      //   return newValue;
      // });
      this.$emit('on-select-all', selection)
    },
    onSelectionChange(selection) {
      this.$emit('on-selection-change', selection)
    },
    onSortChange(column, key, order) {
      this.$emit('on-sort-change', column, key, order)
    },
    onFilterChange(row) {
      this.$emit('on-filter-change', row)
    },
    onRowClick(row, index) {
      this.$emit('on-row-click', row, index)
    },
    onRowDblclick(row, index) {
      this.$emit('on-row-dblclick', row, index)
    },
    onExpand(row, status) {
      this.$emit('on-expand', row, status)
    },
    onSize(pagesize) {
      this.changePageFlag = true
      // this.setPageSize(pagesize);
      this.changePageParams(1, pagesize)
      // this.$emit('on-change-pagesize', pagesize);
    },
    setPageSize(newValue) {
      this.pageSize = newValue || 10
    },
    changePage(page, pageSize) {
      if (this.changePageFlag) {
        this.changePageFlag = false
        return false
      }
      this.$emit('on-change-page', page, pageSize || this.pageSize)
    },
    changePageParams(page, pageSize) {
      this.$emit('on-change-page', page, pageSize || this.pageSize)
    }
  },
  watch: {
    columns(columns) {
      this.handleColumns(columns)
      this.setDefaultSearchKey()
    },
    value(val) {
      this.handleTableData()
      if (this.searchable) this.handleSearch()
    }
  }
}
</script>
